#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Java解析器(JavaParser)：基于两阶段解析策略的Java代码解析实现
负责人：姜郑恒、何江海

主要功能：
1. 改进Java AST解析，实现两阶段解析策略
2. 实现关系解析逻辑，支持引用解析和断点恢复
3. 优化内部类和静态内部类的解析
4. 完善imports解析和引用定位逻辑
"""

import logging
import weakref
from importlib.metadata import metadata
import parser.refactor.name_resolver as name_resolver

from typing import Dict, List, Set, Any, Optional, Tuple
import os

from tree_sitter import Tree, Node, Query

# 导入数据结构
from parser.refactor.data_structures import (
    ParserContext, MetadataInfo, RelationshipCollection, ClassInfo,
    RelationshipInfo, DependencyType, DependencyContext, PackageInfo, FileInfo
)
from parser.refactor.java_metadata_extractor.java_annotation_extractor import JavaAnnotationExtractor
from parser.refactor.java_metadata_extractor.java_class_extractor import JavaClassExtractor
from parser.refactor.java_metadata_extractor.java_comment_extractor import JavaCommentExtractor
from parser.refactor.java_metadata_extractor.java_file_extractor import JavaFileExtractor
from parser.refactor.java_metadata_extractor.java_innner_class_extractor import JavaInnerClassExtractor
from parser.refactor.java_metadata_extractor.java_metadata_extractor import JavaMetadataExtractor
from parser.refactor.java_metadata_extractor.java_method_extractor import JavaMethodExtractor
from parser.refactor.java_node_type import JavaNodeType

# 其他导入
# from parser.ast_to_kg_interface import ASTToKGConverter
# from parser.refactor.manager import ParserManager
# from parser.utils import ContentCompressor

logger = logging.getLogger(__name__)

class JavaParser:
    """Java代码解析器，基于两阶段解析策略"""

    def __init__(self, graph_connection, repo_path):
        """
        初始化Java解析器

        Args:
            graph_connection: 图数据库连接
            repo_path: 项目路径
        """
        # 何江海：初始化解析器
        self.graph_connection = graph_connection
        self.repo_path = repo_path

        # 初始化parser
        self.parser = None
        self._initialize_parser()

        # 跟踪创建的顶点
        self.created_vertices: Set[str] = set()
        self.id_mappings: Dict[str, str] = {}
        self.placeholder_vertices: Set[str] = set()

        # java_scanner扫描后的classList
        self.class_list = []
        # 基于class_list生成的全量类的全限定名的列表, 用于各元数据提取
        self.class_full_name_list = []

    def _initialize_parser(self):
        """初始化Java语法分析器"""
        try:
            # 导入tree-sitter-java
            import tree_sitter_java as tsjava
            from tree_sitter import Language, Parser

            # 初始化Java语言
            JAVA_LANGUAGE = Language(tsjava.language())

            # 创建解析器
            self.parser = Parser(JAVA_LANGUAGE)

            logger.info("Java解析器初始化成功")
        except Exception as e:
            logger.error(f"Java解析器初始化失败: {str(e)}")
            raise

    def parse_file(self, file_path: str) -> Tuple[Optional[Tree], Optional[bytes]]:
        """
        解析Java文件，生成语法树和源码字节

        Args:
            file_path: 要解析的Java文件路径

        Returns:
            (解析生成的语法树对象, 源码字节)，解析失败时返回 (None, None)
        """
        try:
            # 读取文件内容
            with open(file_path, 'r', encoding='utf-8') as f:
                source_code = f.read()

            # 解析代码生成语法树
            code_bytes = source_code.encode('utf-8')
            tree = self.parser.parse(code_bytes)
            return tree, code_bytes
        except Exception as e:
            logger.error(f"解析文件 {file_path} 失败: {str(e)}")
            return None, None

    def extract_metadata(self, tree: Tree, file_path: str, class_name_map: Dict[str, ClassInfo],
                         code_bytes: bytes = None, parser_manager: 'ParserManager' = None,
                         current_metadata_list: List[MetadataInfo] = []) -> List[MetadataInfo]:
        """
        第一阶段：提取元数据（类、方法等基本信息）

        Args:
            tree: 语法树对象
            file_path: 文件路径
            class_name_map: 类名到类信息的映射
            code_bytes: 源代码
            parser_manager: 解析器管理器实例
            current_metadata_list: 当前元数据列表

        Returns:
            元数据对象
        """
        # 姜郑恒：实现元数据提取，基于现有extract_entities方法改进
        # 但专注于提取类和方法的基本信息，不处理关系
        try:
            # 当前文件对应的元数据List, 保存主类及其内部类的metadata, 其中涉及的父类、实现的接口在java_parser的process_file()中处理
            metadata_list=[]

            # 1. 提取包名
            # 将源代码转换为字节形式，用于tree-sitter解析
            java_metadata_extractor = JavaMetadataExtractor()
            root_node = tree.root_node
            package_name = ""
            for node in root_node.children:
                if node.type == JavaNodeType.PACKAGE_DECLARATION:
                    for child in node.children:
                        if child.type == JavaNodeType.SCOPED_IDENTIFIER:
                            package_name = java_metadata_extractor.get_node_text(child, code_bytes)
                            break

            # 2.提取import语句
            import_list = []
            for node in root_node.children:
                if node.type == 'import_declaration':
                    import_text = java_metadata_extractor.get_node_text(node, code_bytes)
                    # 清理import语句，移除import关键字和分号
                    import_text = import_text.replace('import', '').replace(';', '').strip()
                    # 处理static import
                    if import_text.startswith('static'):
                        import_text = import_text.replace('static', '').strip()
                    import_list.append(import_text)

            # 3. 提取文件信息
            java_file_extractor = JavaFileExtractor()
            file_info = java_file_extractor.extract_file_info(file_path, package_name, code_bytes)

            # TODO jzh metadata解析列表
            # 5. 遍历AST，递归处理主类内部信息
            for node in root_node.children:
                temp_metadata_list = self.extract_class_metadata(node, file_path, class_name_map, package_name, import_list,
                                                                file_info, code_bytes, parser_manager, current_metadata_list)
                if temp_metadata_list:
                    metadata_list.extend(temp_metadata_list)

            return metadata_list
        except Exception as e:
            logger.error(f"提取元数据失败: {str(e)}")
            return metadata_list

    def extract_class_metadata(self, node:Node, file_path: str, class_name_map: Dict[str, ClassInfo],
                               package_name: str, import_list: List[str], file_info: FileInfo,
                         code_bytes: bytes = None, parser_manager: 'ParserManager' = None,
                               current_metadata_list: List[MetadataInfo] = []) -> List[MetadataInfo]:
        """
        具体以类维度处理元数据

        Args:
            node: 语法树对象
            file_path: 文件路径
            class_name_map: 类名到类信息的映射
            package_name: 当前文件包名
            import_list: 导入信息列表
            file_info: 文件信息
            code_bytes: 源代码
            parser_manager: 解析器管理器实例
            current_metadata_list: 当前元数据列表

        Returns:
            元数据对象
        """
        metadata_list = []

        try:
            metadata = MetadataInfo(
                file_info={},
                class_info={},
                methods=[],
                comments=[]
            )

            # 1. 设置文件信息
            metadata.file_info = file_info

            # 2. 提取类信息（包括普通类、接口、枚举类型，其中注解单独处理）
            if node.type in [JavaNodeType.CLASS_DECLARATION,
                            JavaNodeType.INTERFACE_DECLARATION,
                            JavaNodeType.ENUM_DECLARATION,
                            JavaNodeType.ANNOTATION_DECLARATION]:

                java_class_extractor = JavaClassExtractor(class_name_map)
                java_comment_extractor = JavaCommentExtractor()
                java_method_extractor = JavaMethodExtractor(class_name_map)

                # 提取类的基本信息
                class_info = java_class_extractor.extract_class_info(file_path, node, code_bytes, package_name,
                                                                      import_list)
                if class_info:
                    # 设置主类的class_info
                    metadata.class_info = class_info

                    # 递归解析父类
                    if class_info.super_classes and parser_manager is not None:
                        for super_class_full_name in class_info.super_classes:
                            super_class = class_name_map.get(super_class_full_name)
                            if super_class:
                                # 父类的metadata在manager中保存
                                result = parser_manager.process_class(super_class, False, False, current_metadata_list)
                                print(f"中断当前类处理, 处理父类[{super_class_full_name}], 处理结果=[{result}]")

                    # 递归解析实现的接口
                    if class_info.implemented_interfaces and parser_manager is not None:
                        for interface_full_name in class_info.implemented_interfaces:
                            interface = class_name_map.get(interface_full_name)
                            if interface:
                                # 实现的接口的metadata在manager中保存
                                result = parser_manager.process_class(interface, False, False, current_metadata_list)
                                print(f"中断当前类处理, 处理实现接口[{interface_full_name}], 处理结果=[{result}]")

                    for class_body_node in node.children:
                        if class_body_node.type in [JavaNodeType.CLASS_BODY, JavaNodeType.INTERFACE_BODY]:
                            for child in class_body_node.children:
                                # 提取类中的方法信息
                                if child.type == JavaNodeType.METHOD_DECLARATION:
                                    method_info = java_method_extractor.extract_method_info(
                                        file_path,
                                        child,
                                        code_bytes,
                                        package_name,
                                        import_list
                                    )
                                    if method_info:
                                        metadata.methods.append(method_info)
                                        # 提取方法注释信息
                                        comment_info = java_comment_extractor.get_comment_info(child, package_name, code_bytes)
                                        if comment_info:
                                            metadata.comments.append(comment_info)

                                # 处理内部类节点
                                elif child.type in [JavaNodeType.CLASS_DECLARATION,
                                                JavaNodeType.INTERFACE_DECLARATION,
                                                JavaNodeType.ENUM_DECLARATION]:
                                    inner_classes = self.extract_class_metadata(child, file_path, class_name_map, package_name, import_list,
                                                                          file_info, code_bytes, parser_manager)
                                    if inner_classes:
                                        for inner_class in inner_classes:
                                            inner_class.class_info.is_inner_class = True
                                            metadata_list.append(inner_class)
                # 提取类注释信息
                comment_info = java_comment_extractor.get_comment_info(node, package_name, code_bytes)
                if comment_info:
                    metadata.comments.append(comment_info)

                # 存入metadata_list中
                metadata_list.append(metadata)

            # 补充当前新提取的元数据
            current_metadata_list.extend(metadata_list)

            return metadata_list
        except Exception as e:
            logger.error(f"具体以类维度处理元数据异常: {str(e)}")
            return metadata_list

    def extract_relationships(self, tree: Tree, file_path: str, metadataList: List[MetadataInfo], code_bytes: bytes = None,
                             parser_manager: 'ParserManager' =None) -> RelationshipCollection:
        """
        第二阶段：提取关系，支持断点恢复

        Args:
            tree: 语法树对象
            file_path: 文件路径
            metadata: 已提取的元数据
            source_code: 源代码字符串（可选）
            parser_manager: 解析管理器，用于处理类引用

        Returns:
            关系集合对象
        """
        try:
            
            # 创建一个以类全名为键的元数据映射
            metadata_map = {}
            for metadata in metadataList:
                if metadata.class_info and hasattr(metadata.class_info, 'full_name') and metadata.class_info.full_name:
                    full_name = metadata.class_info.full_name
                    metadata_map[full_name] = metadata

            # 现在metadata_map包含了所有以class_info.full_name为键的metadata
            # 提取主类信息
            metadata = metadataList[0];
            # 创建关系集合对象
            relationships = RelationshipCollection()

            root_node = tree.root_node

            # 创建类成员变量集合和方法参数/局部变量映射
            class_fields = set()  # 存储类的成员变量
            method_variables: Dict[str, Dict[str, str]] = {}  # 方法全限定名 -> {变量名: 类型全限定名} 的映射

            class_info = metadata.class_info          
            class_full_name = class_info.full_name

            # 处理父类关系
            # ASSUMPTION: class_info_dict.get("super_classes") now returns List[Dict[str, Any]] (ClassInfo-like dicts)
            if class_info.super_classes:
                for super_class_info_full_name in class_info.super_classes:
                    relationship = RelationshipInfo(
                        source_id=class_full_name,
                        target_id=super_class_info_full_name,
                        relationship_type="depends_on",
                        properties={"dependency_type": DependencyType.INHERITANCE.value}
                    )
                    relationships.add_relationship(relationship)

                # 处理接口实现关系
                # ASSUMPTION: class_info_dict.get("implemented_interfaces") now returns List[Dict[str, Any]] (ClassInfo-like dicts)
                if class_info.implemented_interfaces:
                    for interface_info_full_name in class_info.implemented_interfaces:
                        # 添加实现关系
                        relationship = RelationshipInfo(
                            source_id=class_full_name,
                            target_id=interface_info_full_name,
                            relationship_type="depends_on",
                            properties={"dependency_type": DependencyType.IMPLEMENTATION.value}
                        )
                        relationships.add_relationship(relationship)

            # 2. 使用tree-sitter的scm查询提取类成员变量
            field_query = """
            (class_declaration
              body: (class_body
                (field_declaration
                  type: [
                    (type_identifier)
                    (scoped_type_identifier)
                    (generic_type)
                  ] @field_type
                  declarator: (variable_declarator
                    name: (identifier) @field_name))))
            """

            # 执行查询获取类成员变量
            field_matches_dict = self._execute_scm_query(field_query, root_node, code_bytes)
            field_type_nodes = field_matches_dict.get("field_type", [])
            field_name_nodes = field_matches_dict.get("field_name", [])

            for field_type_node, field_name_node in zip(field_type_nodes, field_name_nodes):
                if field_type_node and field_name_node:
                    field_type = self._get_node_text(field_type_node, code_bytes)
                    field_name = self._get_node_text(field_name_node, code_bytes)

                    # 添加到类成员变量集合
                    class_fields.add(field_name)

                    # 检查字段类型是否为自定义类型（非Java基本类型）
                    if self._is_custom_type(field_type):
                        # 为每个类添加字段依赖关系
                        # 创建ParserContext并处理依赖类
                        if parser_manager:
                            context = ParserContext(
                                current_class=class_info,
                                parsing_phase="relationships"
                            )
                            full_field_class = field_type;
                            dependent_class = name_resolver.resolve_full_qualified_name(field_type, class_info, parser_manager._package_list, parser_manager._class_list)
                            if dependent_class:
                                full_field_class = dependent_class;
                            # 添加字段依赖关系
                            relationship = RelationshipInfo(
                                source_id=class_full_name,
                                target_id=full_field_class,
                                relationship_type="depends_on",
                                properties={
                                    "dependency_type": DependencyType.FIELD_ACCESS.value,
                                    "field_name": field_name
                                }
                            )
                            relationships.add_relationship(relationship)

            # 3. 提取方法参数
            # 修改SCM查询以捕获类和方法的关系
            param_query = """
            (class_declaration
              name: (identifier) @class_name
              body: (class_body
                (method_declaration
                  name: (identifier) @method_name
                  parameters: (formal_parameters
                    (formal_parameter
                      type: [
                        (type_identifier)
                        (scoped_type_identifier)
                        (generic_type)
                      ] @param_type
                      name: (identifier) @param_name)))))
            """

            # 执行查询获取方法参数和所属类
            param_matches_dict = self._execute_scm_query(param_query, root_node, code_bytes)
            param_class_name_nodes = param_matches_dict.get("class_name", [])
            param_method_name_nodes = param_matches_dict.get("method_name", [])
            param_param_type_nodes = param_matches_dict.get("param_type", [])
            param_param_name_nodes = param_matches_dict.get("param_name", [])

            # 创建一个映射来存储类名和对应的方法节点
            class_method_map = {}
            for i, (class_name_node, method_name_node) in enumerate(zip(param_class_name_nodes, param_method_name_nodes)):
                if class_name_node and method_name_node:
                    class_name = self._get_node_text(class_name_node, code_bytes)
                    method_name = self._get_node_text(method_name_node, code_bytes)
                    
                    if class_name not in class_method_map:
                        class_method_map[class_name] = []
                    
                    # 存储方法节点和参数节点的索引
                    class_method_map[class_name].append((method_name, i))

            # 处理每个类的方法参数
            for class_name, method_indices in class_method_map.items():
                # 查找对应的类元数据 (class_name是SCM中捕获的简单类名)
                matching_class_info = None
                current_file_info = None # 用于获取imports
                for full_name, meta_obj in metadata_map.items():
                    # 尝试通过全限定名后缀或简单名称匹配来定位元数据
                    if meta_obj.class_info.name == class_name and (full_name.endswith("." + class_name) or meta_obj.class_info.full_name == class_name):
                        # 此处需要更鲁棒的匹配逻辑，特别是处理内部类且名称可能冲突时
                        # 一个更优的策略是在元数据提取阶段就将SCM节点与ClassInfo对象关联起来
                        matching_class_info = meta_obj.class_info
                        current_file_info = meta_obj.file_info
                        break
                
                if not matching_class_info:
                    logger.debug(f"参数提取：找不到类 '{class_name}' 的元数据")
                    continue 
                
                class_full_name_for_param = matching_class_info.full_name
                
                # 处理此类中的每个方法参数
                for method_name, idx in method_indices:
                    param_type_node = param_param_type_nodes[idx]
                    param_name_node = param_param_name_nodes[idx]
                    
                    if param_type_node and param_name_node:
                        param_type_str = self._get_node_text(param_type_node, code_bytes)
                        param_name_str = self._get_node_text(param_name_node, code_bytes)
                        
                        # 查找方法信息
                        for method_info in metadata_map[class_full_name].methods:
                            if method_info.name == method_name:
                                method_full_name = method_info.full_name
                                
                                # 将参数添加到方法变量映射
                                if method_full_name not in method_variables:
                                    method_variables[method_full_name] = {}
                                method_variables[method_full_name][param_name] = param_type
                                
                                # 检查参数类型是否为自定义类型
                                if self._is_custom_type(param_type):
                                    # 创建ParserContext并处理依赖类
                                    if parser_manager:
                                        context = ParserContext(
                                            current_class=matching_class_info,
                                            parsing_phase="relationships"
                                        )
                                        resolved_type = name_resolver.resolve_full_qualified_name(
                                            param_type, 
                                            metadata_map[class_full_name].file_info.imports,
                                            [], # packages list
                                            [], # classes list
                                            matching_class_info
                                        )
                                        if resolved_type:
                                            param_type = resolved_type
                                        parser_manager.handle_dependency_class(param_type, context)
                                    
                                    # 添加参数依赖关系
                                    relationship = RelationshipInfo(
                                        source_id=method_full_name,
                                        target_id=param_type,
                                        relationship_type="depends_on",
                                        properties={
                                            "dependency_type": DependencyType.PARAMETER_TYPE.value,
                                            "param_name": param_name
                                        }
                                    )
                                    relationships.add_relationship(relationship)

            # 4. 提取方法局部变量
            local_var_query = """
            (class_declaration
              name: (identifier) @class_name
              body: (class_body
                (method_declaration
                  name: (identifier) @method_name
                  body: (block
                    (local_variable_declaration
                      type: [
                        (type_identifier)
                        (scoped_type_identifier)
                        (generic_type)
                      ] @var_type
                      declarator: (variable_declarator
                        name: (identifier) @var_name))))))
            """

            local_var_matches_dict = self._execute_scm_query(local_var_query, root_node, code_bytes)
            lv_class_name_nodes = local_var_matches_dict.get("class_name", [])
            lv_method_name_nodes = local_var_matches_dict.get("method_name", [])
            lv_var_type_nodes = local_var_matches_dict.get("var_type", [])
            lv_var_name_nodes = local_var_matches_dict.get("var_name", [])

            for i in range(len(lv_var_name_nodes)):
                class_name_node = lv_class_name_nodes[i]
                method_name_node = lv_method_name_nodes[i]
                var_type_node = lv_var_type_nodes[i]
                var_name_node = lv_var_name_nodes[i]

                class_name_str = self._get_node_text(class_name_node, code_bytes)
                method_name_str = self._get_node_text(method_name_node, code_bytes)
                var_type_str = self._get_node_text(var_type_node, code_bytes)
                var_name_str = self._get_node_text(var_name_node, code_bytes)

                containing_class_info = None
                containing_class_full_name = None
                containing_file_info = None 

                for full_name, meta_info_obj in metadata_map.items():
                    if meta_info_obj.class_info.name == class_name_str: 
                        temp_class_info_check = meta_info_obj.class_info
                        method_exists_in_temp_class = any(m.name == method_name_str for m in temp_class_info_check.methods)
                        if method_exists_in_temp_class:
                            containing_class_info = temp_class_info_check
                            containing_class_full_name = temp_class_info_check.full_name
                            containing_file_info = meta_info_obj.file_info
                            break 
                
                if not containing_class_info:
                    logger.debug(f"局部变量提取：找不到类 '{class_name_str}' (包含方法 '{method_name_str}') 的元数据。")
                    continue

                method_info_obj = None
                for m_info in containing_class_info.methods:
                    if m_info.name == method_name_str: 
                        method_info_obj = m_info
                        break
                
                if not method_info_obj:
                    logger.debug(f"局部变量提取：在类 '{containing_class_full_name}' 中找不到方法 '{method_name_str}' 的元数据。")
                    continue
                
                method_full_name = method_info_obj.full_name

                resolved_var_type = name_resolver.resolve_full_qualified_name(
                    var_type_str,
                    containing_file_info.imports if containing_file_info else [],
                    parser_manager._package_list if parser_manager else [],
                    parser_manager._class_list if parser_manager else [],
                    containing_class_info
                )
                actual_var_type_for_relationship = resolved_var_type if resolved_var_type else var_type_str

                if method_full_name not in method_variables:
                    method_variables[method_full_name] = {}
                method_variables[method_full_name][var_name_str] = actual_var_type_for_relationship

                if self._is_custom_type(actual_var_type_for_relationship):
                    if parser_manager:
                        context = ParserContext(
                            current_class=containing_class_info,
                            parsing_phase="relationships"
                        )
                        parser_manager.handle_dependency_class(actual_var_type_for_relationship, context)
                    
                    relationship = RelationshipInfo(
                        source_id=method_full_name, 
                        target_id=actual_var_type_for_relationship, 
                        relationship_type="depends_on",
                        properties={
                            "dependency_type": DependencyType.VARIABLE_TYPE.value,
                            "var_name": var_name_str
                        }
                    )
                    relationships.add_relationship(relationship)

            # 5. 提取方法内部调用其他方法的call语句 (同类或父类方法)
            # SCM 查询捕获调用方类名、方法名，以及被调用方法的简单名称和方法调用节点本身。
            method_call_query = """
            (class_declaration
              name: (identifier) @class_name
              body: (class_body
                (method_declaration
                  name: (identifier) @method_name # Calling method / 调用方方法
                  body: (block
                    (expression_statement
                      (method_invocation as @invocation_node # 捕获方法调用节点本身
                        name: (identifier) @called_method_name
                      ))))))
            """
            # 后续Python代码将检查 @invocation_node 的 'object' 字段来区分:
            # - foo() (object 不存在)
            # - this.foo() (object 是 this_expression)
            # - myVar.foo() (object 是 identifier, 应由第6步处理)

            mc_matches_dict = self._execute_scm_query(method_call_query, root_node, code_bytes)
            mc_class_name_nodes = mc_matches_dict.get("class_name", [])
            mc_method_name_nodes = mc_matches_dict.get("method_name", [])
            mc_invocation_nodes = mc_matches_dict.get("invocation_node", []) 
            mc_called_method_name_nodes = mc_matches_dict.get("called_method_name", [])

            for i in range(len(mc_called_method_name_nodes)):
                class_name_node = mc_class_name_nodes[i]
                method_name_node = mc_method_name_nodes[i]
                invocation_node = mc_invocation_nodes[i] 
                called_method_name_node = mc_called_method_name_nodes[i]

                class_name_str = self._get_node_text(class_name_node, code_bytes)
                calling_method_name_str = self._get_node_text(method_name_node, code_bytes)
                called_method_name_str = self._get_node_text(called_method_name_node, code_bytes)

                object_node = invocation_node.child_by_field_name("object")

                if object_node is None:
                    logger.debug(f"同类方法调用(隐式this): {class_name_str}.{calling_method_name_str} -> {called_method_name_str}()")
                elif object_node.type == JavaNodeType.THIS_EXPRESSION:
                    logger.debug(f"同类方法调用(显式this): {class_name_str}.{calling_method_name_str} -> this.{called_method_name_str}()")
                else:
                    logger.debug(f"同类方法调用检测：调用 '{self._get_node_text(invocation_node, code_bytes)}' 的 object 类型为 '{object_node.type}'，将由第6步处理。")
                    continue 

                calling_class_info = None
                calling_class_full_name = None
                for full_name, meta_info_obj in metadata_map.items():
                    if meta_info_obj.class_info.name == class_name_str: 
                        temp_class_info = meta_info_obj.class_info
                        if any(m.name == calling_method_name_str for m in temp_class_info.methods):
                            calling_class_info = temp_class_info
                            calling_class_full_name = temp_class_info.full_name
                            break
                
                if not calling_class_info:
                    logger.debug(f"同类方法调用：找不到类 '{class_name_str}' 的元数据")
                    continue

                calling_method_info_obj = None
                for m_info in calling_class_info.methods:
                    if m_info.name == calling_method_name_str: 
                        calling_method_info_obj = m_info
                        break
                if not calling_method_info_obj:
                    logger.debug(f"同类方法调用：在类 '{calling_class_full_name}' 中找不到调用方方法 '{calling_method_name_str}'\'\')") # Fixed apostrophe and parenthesis
                    continue
                
                caller_method_full_name = calling_method_info_obj.full_name
                resolved_called_method_full_name = None

                for m_info in calling_class_info.methods:
                    if m_info.name == called_method_name_str: 
                        resolved_called_method_full_name = m_info.full_name
                        break
                
                if not resolved_called_method_full_name:
                    processed_supers = set() 
                    super_queue = list(calling_class_info.super_classes) 
                    
                    while super_queue:
                        super_class_full_name = super_queue.pop(0)
                        if super_class_full_name in processed_supers:
                            continue
                        processed_supers.add(super_class_full_name)

                        super_class_metadata = metadata_map.get(super_class_full_name)
                        if super_class_metadata:
                            super_class_actual_info = super_class_metadata.class_info
                            for m_info in super_class_actual_info.methods:
                                if m_info.name == called_method_name_str: 
                                    resolved_called_method_full_name = m_info.full_name
                                    break 
                            if resolved_called_method_full_name:
                                break 

                if resolved_called_method_full_name:
                    relationship = RelationshipInfo(
                        source_id=caller_method_full_name,
                        target_id=resolved_called_method_full_name,
                        relationship_type="depends_on",
                        properties={"dependency_type": DependencyType.METHOD_CALL.value}
                    )
                    relationships.add_relationship(relationship)

            # 6. 提取方法调用其他类中方法的call语句
            other_class_call_query = """
            (class_declaration
              name: (identifier) @class_name # Class of the calling method
              body: (class_body
                (method_declaration
                  name: (identifier) @method_name # Calling method
                  body: (block
                    (expression_statement
                      (method_invocation
                        object: [
                              (identifier) @object_name  # Catches simple identifiers like 'obj' or 'ClassName'
                              (field_access               # Catches obj.field or ClassName.field
                            object: (identifier) @object_name
                                # field: (identifier) @field_name_in_call # field_name_in_call not used for object type
                              )
                              (scoped_identifier) @object_name # Catches com.example.ClassName for FQNs
                              # (method_invocation) @object_name # For chained calls like getObj().call(), @object_name would be getObj node
                            ]
                            name: (identifier) @called_method_name))))))
            """
            # The @object_name capture needs to be robust. If it's (scoped_identifier), text is FQN.
            # If it's (identifier), text is simple name.
            # If it's part of field_access, @object_name is the identifier of the field_access's object.

            occ_matches_dict = self._execute_scm_query(other_class_call_query, root_node, code_bytes)
            occ_class_name_nodes = occ_matches_dict.get("class_name", [])
            occ_method_name_nodes = occ_matches_dict.get("method_name", [])
            occ_object_name_nodes = occ_matches_dict.get("object_name", []) # Node for the object part
            occ_called_method_name_nodes = occ_matches_dict.get("called_method_name", [])
            
            for i in range(len(occ_called_method_name_nodes)):
                class_name_node = occ_class_name_nodes[i]
                method_name_node = occ_method_name_nodes[i]
                object_node = occ_object_name_nodes[i] # This is a node
                called_method_name_node = occ_called_method_name_nodes[i]

                class_name_str = self._get_node_text(class_name_node, code_bytes)
                calling_method_name_str = self._get_node_text(method_name_node, code_bytes)
                object_name_str = self._get_node_text(object_node, code_bytes) # Text of the object identifier/FQN
                called_method_name_str = self._get_node_text(called_method_name_node, code_bytes)

                # 查找调用方方法所在的类元数据
                calling_class_info = None
                calling_class_full_name = None
                calling_file_info = None # 用于获取imports以解析object_name_str
                for full_name, meta_info_obj in metadata_map.items():
                    if meta_info_obj.class_info.name == class_name_str: # 简化匹配
                        temp_class_info = meta_info_obj.class_info
                        # 确保这个类确实包含了调用方方法
                        if any(m.name == calling_method_name_str for m in temp_class_info.methods):
                            calling_class_info = temp_class_info
                            calling_class_full_name = temp_class_info.full_name
                            calling_file_info = meta_info_obj.file_info # 保存文件信息
                            break
                
                if not calling_class_info:
                    logger.debug(f"跨类方法调用：找不到类 '{class_name_str}' 的元数据。")
                    continue

                # 查找调用方方法的元数据
                calling_method_info_obj = None
                for m_info in calling_class_info.methods:
                    if m_info.name == calling_method_name_str: # 注意：未处理方法重载
                        calling_method_info_obj = m_info
                        break
                if not calling_method_info_obj:
                    logger.debug(f"跨类方法调用：在类 '{calling_class_full_name}' 中找不到调用方方法 '{calling_method_name_str}'")
                    continue
                caller_method_full_name = calling_method_info_obj.full_name

                object_type_full_name = None # 用于存储解析出的调用对象的全限定类型名

                # 步骤1: 检查调用对象是否为方法参数或局部变量
                if caller_method_full_name in method_variables and object_name_str in method_variables[caller_method_full_name]:
                    object_type_full_name = method_variables[caller_method_full_name][object_name_str]
                
                # 步骤2: 如果不是，检查是否为调用方类的成员变量 (字段)
                if not object_type_full_name:
                    # calling_class_info.fields 应该包含字段的类型信息 (假设已解析为全限定名)
                    for field_info in calling_class_info.fields: 
                        if field_info.name == object_name_str:
                            object_type_full_name = field_info.type # field_info.type 应为字段的类型全名
                            break
                
                # 步骤3: 如果还不是，则假定 object_name_str 是一个类名 (可能是简单名称或全限定名)
                if not object_type_full_name:
                    # 判断 object_name_str 是否可能是全限定名 (FQN)
                    # object_node.type 可以提供额外线索，例如 scoped_identifier 通常是FQN
                    is_fqn_candidate = '.' in object_name_str or object_node.type == JavaNodeType.SCOPED_IDENTIFIER

                    if is_fqn_candidate:
                        # 如果看起来像FQN或来自scoped_identifier，直接使用。
                        # 后续仍然可以考虑通过 name_resolver 或 parser_manager 确认其有效性。
                        object_type_full_name = object_name_str
                    else: # 是简单名称，尝试使用 name_resolver 解析
                        resolved_name = name_resolver.resolve_full_qualified_name(
                            object_name_str, # 要解析的简单名称
                            calling_file_info.imports if calling_file_info else [], # 当前文件的导入信息
                            parser_manager._package_list if parser_manager else [], # 项目的包列表
                            parser_manager._class_list if parser_manager else [],   # 项目的类列表
                            calling_class_info # 调用方方法所在的类的信息 (用于内部类等上下文)
                        )
                        if resolved_name:
                            object_type_full_name = resolved_name
                        else:
                            # 未能通过 name_resolver 解析，可能是未显式导入的同包类，或外部依赖的类。
                            # 作为回退，直接使用 object_name_str，寄希望于后续图查询等方式能找到它。
                            object_type_full_name = object_name_str 
                            logger.debug(f"跨类方法调用：对象 '{object_name_str}' (简单名称) 未能通过 name_resolver 解析。将直接使用。")


                if not object_type_full_name:
                    logger.debug(f"跨类方法调用：无法确定对象 '{object_name_str}' (在方法 '{caller_method_full_name}' 中) 的类型。跳过对此调用的处理：'{called_method_name_str}'\")")
                    continue

                # 如果对象类型是自定义类型，则处理其依赖
                if parser_manager and self._is_custom_type(object_type_full_name):
                    context = ParserContext(current_class=calling_class_info, parsing_phase="relationships")
                    parser_manager.handle_dependency_class(object_type_full_name, context)

                resolved_target_method_full_name = None # 被调用方法的全限定名
                target_class_metadata = metadata_map.get(object_type_full_name) # 从已解析的元数据中查找目标类
                
                if target_class_metadata:
                    target_class_actual_info = target_class_metadata.class_info
                    for m_info in target_class_actual_info.methods:
                        if m_info.name == called_method_name_str: # 注意：未处理方法重载
                            resolved_target_method_full_name = m_info.full_name
                            break
                    # TODO: 如果在直接方法中未找到，还应查找目标类的父类和接口中的方法。
                
                # 如果在本地元数据中未找到，并且图数据库连接可用，则尝试从图数据库查询
                # (注意：确保 object_type_full_name 此时确实是目标类的全限定名)
                if not resolved_target_method_full_name and self.graph_connection:
                    graph_query = f"""
                                    MATCH (c:class)-[:contains]->(m:function)
                    WHERE (c.class.full_name = '{object_type_full_name}' OR c.class.name = '{object_type_full_name}') AND m.function.name = '{called_method_name_str}'
                    RETURN m.function.full_name AS full_name LIMIT 1
                    """
                    success, result_proxy = self.graph_connection.execute_query(graph_query)
                    if success and result_proxy:
                        # 处理图查询结果 (不同图数据库客户端返回结果的方式可能不同)
                        actual_results = []
                        if hasattr(result_proxy, 'rows') and callable(result_proxy.rows): # 兼容某些客户端的 rows() 方法
                             rows_gen = result_proxy.rows()
                             if rows_gen: actual_results = list(rows_gen)
                        elif isinstance(result_proxy, list): # 如果直接返回列表
                            actual_results = result_proxy

                        if actual_results:
                            record = actual_results[0]
                            temp_name = None
                            if hasattr(record, 'values') and callable(record.values): # 记录是带 values 方法的对象
                                temp_name = record.values[0]
                            elif isinstance(record, dict) and 'full_name' in record: # 记录是字典
                                temp_name = record['full_name']
                            else: # 其他情况，尝试作为列表/元组访问第一个元素
                                try: temp_name = record[0]
                                except: pass # 获取失败
                            
                            if temp_name:
                                resolved_target_method_full_name = temp_name.decode('utf-8') if isinstance(temp_name, bytes) else str(temp_name)


                if resolved_target_method_full_name:
                    relationship = RelationshipInfo(
                        source_id=caller_method_full_name, 
                        target_id=resolved_target_method_full_name, 
                        relationship_type="depends_on",
                        properties={"dependency_type": DependencyType.METHOD_CALL.value}
                    )
                    relationships.add_relationship(relationship)

                    # 如果调用方类和目标对象类型不同，添加类之间的依赖关系
                    if calling_class_full_name != object_type_full_name:
                        class_relationship = RelationshipInfo(
                            source_id=calling_class_full_name,    
                            target_id=object_type_full_name,      
                            relationship_type="depends_on",
                            properties={"dependency_type": DependencyType.CLASS_REFERENCE.value} 
                        )
                        relationships.add_relationship(class_relationship)
                else:
                    logger.debug(f"跨类方法调用：在类型 '{object_type_full_name}' 上未能解析目标方法 '{called_method_name_str}' (从方法 '{caller_method_full_name}' 调用)。")

            return relationships
        except Exception as e:
            logger.error(f"提取关系失败: {str(e)}")
            return RelationshipCollection()

    def resume_parsing(self, context: ParserContext, parser_manager):
        """
        从断点恢复解析

        Args:
            context: 解析上下文
            parser_manager: 解析管理器

        Returns:
            解析结果
        """
        # 何江海：实现从断点恢复解析的逻辑
        pass

    def resolve_class_reference(self, ref_name: str, context: ParserContext, parser_manager) -> str:
        """
        解析类引用，支持不同的导入方式

        Args:
            ref_name: 引用名称
            context: 当前上下文
            parser_manager: 解析管理器

        Returns:
            解析后的全限定类名
        """
        # 姜郑恒：实现类引用解析逻辑，支持各种导入方式
        pass

    def _execute_scm_query(self, query_string: str, node: Node, code_bytes: bytes) -> dict:
        """
        执行SCM查询并返回捕获名到节点列表的字典

        Args:
            query_string: SCM查询字符串
            node: 要查询的节点
            code_bytes: 源代码字节

        Returns:
            dict: {捕获名: [Node, ...], ...}
        """
        try:
            language = self.parser.language
            query = Query(language, query_string)
            captures = query.captures(node)
            # captures: List[Tuple[Node, str]] or dict by new API
            # 兼容新版API，直接返回字典
            if isinstance(captures, dict):
                return captures
            # 兼容旧版API，手动组装字典
            result = {}
            for node, capture_name in captures:
                result.setdefault(capture_name, []).append(node)
            return result
        except Exception as e:
            logger.error(f"执行SCM查询失败: {str(e)}")
            return {}

    def _get_node_text(self, node: Node, code_bytes: bytes) -> str:
        """
        获取节点的文本内容

        Args:
            node: 节点
            code_bytes: 源代码字节

        Returns:
            节点的文本内容
        """
        try:
            start_byte = node.start_byte
            end_byte = node.end_byte
            return code_bytes[start_byte:end_byte].decode('utf-8')
        except Exception as e:
            logger.error(f"获取节点文本失败: {str(e)}")
            return ""

    def _is_custom_type(self, type_name: str) -> bool:
        """
        判断类型是否为自定义类型（非Java基本类型）

        Args:
            type_name: 类型名称

        Returns:
            是否为自定义类型
        """
        # Java基本类型和常见标准库类型
        basic_types = [
            "int", "long", "double", "float", "boolean", "char", "byte", "short",
            "String", "Object", "Integer", "Long", "Double", "Float", "Boolean",
            "Character", "Byte", "Short"
        ]
        primitive_arrays = [
            "int[]", "long[]", "double[]", "float[]", "boolean[]", "char[]",
            "byte[]", "short[]", "String[]", "Object[]"
        ]
        collection_types = [
            "List", "ArrayList", "Set", "HashSet", "Map", "HashMap", "Collection"
        ]

        # 排除基本类型、原始数组、Java集合类型和以java.开头的标准库类型
        return (type_name not in basic_types and
                type_name not in primitive_arrays and
                type_name not in collection_types and
                not type_name.startswith("java."))

    def _find_class_info_by_name(self, class_full_name: str) -> Optional[ClassInfo]:
        """
        根据全限定类名查找类信息

        Args:
            class_full_name: 类的全限定名

        Returns:
            类信息对象，如果未找到则返回None
        """
        for class_info in self.class_list:
            if class_info.full_name == class_full_name:
                return class_info
        return None

    